﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Web.UI;
using System.Web.UI.WebControls;
using Utility;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using System.Threading.Tasks;
using System.Text;

namespace WebRole
{
    public partial class _Default : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
            initializeStorage();
        }

        protected void btnBlob_Click(object sender, EventArgs e)
        {
            txtBName.Text = "blob";
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            BlobHelper blobObject = new BlobHelper(connectionString);
            blobObject.PutBlob(DataConstants.BLOB_CONTAINER, DataConstants.BENCH_PAGE_BLOB, DataConstants.BLOB_SIZE);
            QueueHelper queueObject = new QueueHelper(connectionString);
            queueObject.ClearMessages(DataConstants.RESULT_QUEUE);
            queueObject.ClearMessages(DataConstants.INPUT_PARAS);
            queueObject.PutMessage(DataConstants.INPUT_PARAS, new CloudQueueMessage("blob"));
            txtStatus.Text += "\nBlob benchmarking started at " + DateTime.Now.ToString() + ".";
            tmrStatus.Enabled = true;
            disableClicks();
        }

        protected void tmrStatus_Tick(object sender, EventArgs e)
        {
            int numberCompleteProcess;
            int numberOfWorkers = RoleEnvironment.Roles["WorkerRole"].Instances.Count;
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);

            queueObject.GetApproxMessageCount(DataConstants.RESULT_QUEUE, out numberCompleteProcess);
            if (numberCompleteProcess > 0)
            {
                if (numberCompleteProcess == numberOfWorkers)
                {
                    txtStatus.Text += "\nBenchmarking ends at " + DateTime.Now.ToString() + ".";
                    lblStatus.Text = "";
                    btnResults.Visible = true;
                    tmrStatus.Enabled = false;
                }
                else
                {
                    lblStatus.Text = "\nBenchmarking is finished by " + numberCompleteProcess + " worker role instances.";
                }
            }
        }

        protected void btnQueue_Click(object sender, EventArgs e)
        {
            txtBName.Text = "queue";
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);
            queueObject.ClearMessages(DataConstants.RESULT_QUEUE);
            queueObject.ClearMessages(DataConstants.INPUT_PARAS);
            queueObject.PutMessage(DataConstants.INPUT_PARAS, new CloudQueueMessage("queue"));
            txtStatus.Text += "\nQueue benchmarking started at " + DateTime.Now.ToString() + ".";
            tmrStatus.Enabled = true;
            disableClicks();
        }

        protected void btnTable_Click(object sender, EventArgs e)
        {
            txtBName.Text = "table";
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);
            queueObject.ClearMessages(DataConstants.RESULT_QUEUE);
            queueObject.ClearMessages(DataConstants.INPUT_PARAS);
            queueObject.PutMessage(DataConstants.INPUT_PARAS, new CloudQueueMessage("table"));
            txtStatus.Text += "\nTable benchmarking started at " + DateTime.Now.ToString() + ".";
            tmrStatus.Enabled = true;
            disableClicks();
        }

        protected void btnResults_Click(object sender, EventArgs e)
        {
            List<double> results = new List<double>();
            string header = string.Empty;
            if (txtBName.Text == "blob")
            {
                string txtResult = string.Empty;
                results = fetchResults(10).ToList();
                txtResult = "\nPage(U)\tBlock(U)\tPageB(D)\tBlock(D)IndiPage(U)\tIndiBlock(U)\tIndiPage(D)\tIndiBlock(D)\tRandomPageAccess\tBlobstreamdownload" + "\n________________________________________________________________\n";

                for (int i = 0; i < results.Count; i++)
                {
                    txtResult += results[i].ToString() + "\t";
                }
                System.Diagnostics.Trace.WriteLine(txtResult);
                txtStatus.Text += txtResult;

            }

            if (txtBName.Text == "table")
            {
                TableHelper tableObject = new TableHelper(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));
                tableObject.CreateTable(DataConstants.BENCH_TABLE);
                results.Clear();
                results = fetchResults(20).ToList();
                header = "\nSize\tInsert\tQuery\tUpdate\tDelete" + "\n________________________________________________________________";
                txtStatus.Text += header;
                int size = DataConstants.TABLE_ENTITY_SIZE;
                string txtResult = string.Empty;

                for (int i = 0; i < 5; i++)
                {
                    size = size * 2;
                    txtResult += "\n" + size.ToString();
                    for (int j = 0; j < 4; j++)
                    {
                        txtResult += "\t" + results[i * 4 + j].ToString();
                    }
                }
                System.Diagnostics.Trace.WriteLine(txtResult);
                txtStatus.Text += txtResult;
            }

            if (txtBName.Text == "queue")
            {
                results.Clear();
                results = fetchResults(30).ToList();
                header = "\nSize\tCount\tPut(S)\tPeek(S)\tGet(S)" + "\n________________________________________________________________";
                txtStatus.Text += header;
                string txtResult = string.Empty;

                int size = DataConstants.MSG_SIZE;
                for (int k = 0; k < 5; k++)
                {
                    size = size * 2;
                    txtResult += "\n" + size.ToString();
                    txtResult += "\t" + DataConstants.MSG_COUNT_LARGE;
                    for (int j = 0; j < 3; j++)
                    {
                        txtResult += "\t" + results[k * 3 + j].ToString();
                    }
                }

                header = "\nThinktime\tPut(S)\tPeek(S)\tGet(S)" + "\n________________________________________________________________";
                txtStatus.Text += header;
                int thinkTime = DataConstants.THINK_TIME;
                for (int k = 0; k < 5; k++)
                {
                    thinkTime = thinkTime * 2;
                    txtResult += "\n" + thinkTime.ToString();
                    for (int j = 0; j < 3; j++)
                    {
                        txtResult += "\t" + results[15 + k * 3 + j].ToString();
                    }
                }
                System.Diagnostics.Trace.WriteLine(txtResult);
                txtStatus.Text += txtResult;
            }

            if (txtBName.Text == "sql")
            {
                string txtResult = string.Empty;
                results.Clear();
                results = fetchResults(6).ToList();
                header = "\nCreate\tInsert\tUpdate\tSelect\tDelete\tDrop" + "\n________________________________________________________________________\n";
                txtStatus.Text += header;
                for (int i = 0; i < 6; i++)
                {
                    txtResult += "\t" + results[i].ToString();
                }

                System.Diagnostics.Trace.WriteLine(txtResult);
                txtStatus.Text += txtResult;

            }

            btnResults.Visible = false;
            enableClicks();
            txtBName.Text = string.Empty;
        }

        private double[] fetchResults(int numberOfResult)
        {
            double[] results = new double[numberOfResult];
            string[] resultStr = new string[numberOfResult];

            /* Initialize to 0 */
            for (int j = 0; j < numberOfResult; j++)
            {
                results[j] = 0;
            }

            CloudQueueMessage msg = new CloudQueueMessage("");
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);

            int numberOfWorkers = RoleEnvironment.Roles["WorkerRole"].Instances.Count;
            /* Read all messages - one at a time */
            for (int i = 0; i < numberOfWorkers; i++)
            {
                queueObject.GetMessage(DataConstants.RESULT_QUEUE, out msg);
                resultStr = (msg.AsString).Split(',');
                /* Add this worker's time to total time */
                for (int j = 0; j < numberOfResult; j++)
                {
                    results[j] += double.Parse(resultStr[j]);
                }
                queueObject.DeleteMessage(DataConstants.RESULT_QUEUE, msg);
            }

            /* Find average time */
            for (int j = 0; j < numberOfResult; j++)
            {
                results[j] = results[j] / numberOfWorkers;
            }

            return results;
        }

        private void disableClicks()
        {
            btnBlob.Enabled = false;
            btnQueue.Enabled = false;
            btnTable.Enabled = false;
            btnSQL.Enabled = false;
            btnTCP.Enabled = false;
        }

        private void enableClicks()
        {
            btnBlob.Enabled = true;
            btnQueue.Enabled = true;
            btnTable.Enabled = true;
            btnSQL.Enabled = true;
            btnTCP.Enabled = true;
        }

        private void initializeStorage()
        {
            try
            {
                /* Create all entities required for processing */
                string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
                BlobHelper blobObject = new BlobHelper(connectionString);
                blobObject.CreateContainer(DataConstants.BLOB_CONTAINER);

                QueueHelper queueObject = new QueueHelper(connectionString);
                queueObject.CreateQueue(DataConstants.BENCH_QUEUE);
                queueObject.CreateQueue(DataConstants.INPUT_PARAS);
                queueObject.CreateQueue(DataConstants.RESULT_QUEUE);
                queueObject.CreateQueue(DataConstants.WORKER_TERMINATION_INDICATOR);

                TableHelper tableObject = new TableHelper(connectionString);
                tableObject.CreateTable(DataConstants.BENCH_TABLE);
            }
            catch (Exception e)
            {
                System.Diagnostics.Trace.WriteLine("I was not able to create all the storage entities. Please check if the configurations are ok. Error message:" + e.Message.ToString());
            }
        }


        protected void btnTCP_Click(object sender, EventArgs e)
        {
            txtBName.Text = "tcp";
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);
            queueObject.ClearMessages(DataConstants.RESULT_QUEUE);
            queueObject.ClearMessages(DataConstants.INPUT_PARAS);
            queueObject.PutMessage(DataConstants.INPUT_PARAS, new CloudQueueMessage("tcp"));
            txtStatus.Text += "\nTCP communication benchmarking started at " + DateTime.Now.ToString() + ".";
            tmrStatus.Enabled = true;
            disableClicks();
        }

        protected void btnSQL_Click(object sender, EventArgs e)
        {
            txtBName.Text = "sql";
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString");
            QueueHelper queueObject = new QueueHelper(connectionString);
            queueObject.ClearMessages(DataConstants.RESULT_QUEUE);
            queueObject.ClearMessages(DataConstants.INPUT_PARAS);
            queueObject.PutMessage(DataConstants.INPUT_PARAS, new CloudQueueMessage("sql"));
            txtStatus.Text += "\nAzure SQL benchmarking started at " + DateTime.Now.ToString() + ".";
            tmrStatus.Enabled = true;
            disableClicks();
        }

       
    }
}